#include "path_sfx.h"
#include "ui/ui_widget.h"
#include "font/font.h"
#include "num/rand.h"
#include "graphics/graphics_util.h"

#include "util/timer.h"				// log
#include "util/log.h"				// log
#include "util/common_macros.h"		// macros
#include "util/mmgr.h"		    

#include <math.h>
#include <stdlib.h>

using namespace vfx;


static const int			MAX_VERT = 600;
static Graphics::Vertex2D	VertA[MAX_VERT];


PathSFX::PathSFX(EffectMan*	pParent, const std::string& Image, float Width) :
	SFXSet(pParent),
	m_Width(Width),
	m_Additive(true)
{
	m_Sprite.Create(Image);
}

PathSFX::~PathSFX()
{
	for (unsigned int i=0; i<m_Paths.size(); i++)
		delete m_Paths[i];
	m_Paths.resize(0);
}

void					PathSFX::Render(const math::Vec2& Offset,float Scale)
{
	Graphics* pG = GetGraphics();
	const COLOR	c = 0xFFFFFFFF;
	int	Index = 0;

	if (m_Additive)
    {
		pG->SetRenderState( Graphics::RS_SRC_BLEND,  Graphics::RV_BLEND_SRC_ALPHA );
		pG->SetRenderState( Graphics::RS_DST_BLEND,  Graphics::RV_BLEND_ONE );
		pG->SetRenderState(Graphics::RS_ALPHA_TEST, false);
	} 
	ui::SpriteInstance*		pSprite = m_Sprite.GetSpriteInst();
	math::Vec2				UV1 = m_Sprite.GetUV1();
	math::Vec2				UV2 = m_Sprite.GetUV2();
	for (unsigned int i=0; i<m_Paths.size(); i++)
	{
		PathInst*	pNode = m_Paths[i];

		if (pSprite)
		{
			pSprite->GetUV(pNode->WaveOffset, UV1, UV2);
		}
		Index += GraphicsUtil::FillRotQuad(pNode->Pos - Offset, m_Sprite.m_Size, pNode->WaveOffset, UV1, UV2, pNode->Color, &VertA[Index]);
		if (Index+10 >= MAX_VERT)
		{
			pG->SetTexture(0, m_Sprite.GetImage());
			pG->DrawVertex2D(VertA, Index);
			Index = 0;
		}
	}
	if (Index > 0 ) 
	{
		pG->SetTexture(0, m_Sprite.GetImage());
		pG->DrawVertex2D(VertA, Index);
	}
	if (m_Additive)
    {
		pG->SetRenderState( Graphics::RS_SRC_BLEND,  Graphics::RV_BLEND_SRC_ALPHA );
		pG->SetRenderState( Graphics::RS_DST_BLEND,  Graphics::RV_BLEND_INVSRC_ALPHA );
		pG->SetRenderState(Graphics::RS_ALPHA_TEST, true);
    } 
}

void					PathSFX::Tick(float dt)
{
	for (int i=int(m_Paths.size())-1; i>=0; i--)
	{
		PathInst*	pInst = m_Paths[i];
		pInst->Prog.Tick(dt);
		if (pInst->Prog.IsReady())
		{
			delete pInst;
			m_Paths.erase(m_Paths.begin()+i);
			continue;
		}


		pInst->WaveOffset+=dt;
		// get the base position
		pInst->Pos = pInst->pSpline->GetPos(pInst->Prog.GetProgress() * pInst->pSpline->GetTrackLen());

		// get the future and delta
		math::Vec2	Next = pInst->pSpline->GetPos(pInst->Prog.GetProgress() * pInst->pSpline->GetTrackLen() * 1.01f);
		math::Vec2	Delta = Next-pInst->Pos;
		
		// rotate Delta 90 degrees
		float	Temp = Delta.x;
		Delta.x = Delta.y;
		Delta.y = -Temp;
		Delta.Normalize();

		// get the random offset
		float	Offset = sinf(pInst->WaveOffset * 4.0f) * m_Width;
		pInst->Pos = pInst->Pos + (Delta*Offset);



	}
}

void					PathSFX::AddElement(math::Spline2D* pPath, float Time)
{
	if (!pPath) return;
	PathInst*	pInst = new PathInst;
	pInst->pSpline = pPath;
	pInst->Prog.SetLimit(Time);
	pInst->WaveOffset = num::RAND32::Instance().RandFloat(0, 10);
	pInst->Pos = pPath->GetPos(0);

		pInst->Color = 0xFFFFFFFF;
		int	Col = rand() % 5;
		switch (Col)
		{
			case 0:	pInst->Color = ColorRGBA(255, 0, 0); break;
			case 1:	pInst->Color = ColorRGBA(0, 255, 0); break;
			case 2:	pInst->Color = ColorRGBA(0, 0, 255); break;
			case 3:	pInst->Color = ColorRGBA(255, 255, 0); break;
			case 4:	pInst->Color = ColorRGBA(255, 0, 255); break;
		}

	m_Paths.push_back(pInst);

}